package com.ideaaedi.commonds.rank;


import java.util.ArrayList;
import java.util.List;

/**
 * 排名实现器
 *
 * @author <font size = "20" color = "#3CAA3C"><a href="https://gitee.com/JustryDeng">JustryDeng</a></font> <img src="https://gitee.com/JustryDeng/shared-files/raw/master/JustryDeng/avatar.jpg" />
 * @since 1.0.0
 */
public interface RankSupporter<T extends Rankable<T>> {
    
    /**
     * 自然排名
     * <br/>
     * 如: 假设分数是100、90、80、80、70，降序排序，那么NATURAL排名后排名是1、2、3、4、5
     * <br/>
     * @param nonNullSortedList
     *            非空集合(集合本身不为空， 集合里面的元素全都不为null; 且这是一个有序的集合)
     * @return 排完名次后的集合
     */
    List<T> natural(List<T> nonNullSortedList);
    
    /**
     * 相同值则排名相同， 后面那个不同的则排名一下跳至对应的位置
     * <br/>
     * 如: 假设分数是100、90、80、80、70，降序排序，那么SAME_RAKE_INDEX_POSTPONED排名后排名是1、2、3、3、5
     * <br/>
     * @param nonNullSortedList
     *            非空集合(集合本身不为空， 集合里面的元素全都不为null; 且这是一个有序的集合)
     * @return 排完名次后的集合
     */
    List<T> indexPostponedIfSame(List<T> nonNullSortedList);
    
    /**
     * 相同值则排名相同， 后面那个不同的则排名+1
     * <br/>
     * 如: 假设分数是100、90、80、80、70，降序排序，那么SAME_RAKE_RANK_POSTPONED排名后排名是1、2、3、3、4
     * <br/>
     * @param nonNullSortedList
     *            非空集合(集合本身不为空， 集合里面的元素全都不为null; 且这是一个有序的集合)
     * @return 排完名次后的集合
     */
    List<T> rankPostponedIfSame(List<T> nonNullSortedList);
    
    /**
     * 自定义排名
     *
     * @param nonNullSortedList
     *            非空集合(集合本身不为空， 集合里面的元素全都不为null; 且这是一个有序的集合)
     * @return 排完名次后的集合
     */
    default List<T> customized(List<T> nonNullSortedList) {
        throw new UnsupportedOperationException("temporarily does not support custom sorting");
    }
    
    /**
     * 排名起始值
     *
     * @return 排名起始值
     */
    default int rankStartValue() {
        return 1;
    }
    
    /**
     * 排名
     *
     * @param nonNullSortedList
     *         已经排过序的数据
     * @param rankStrategy
     *         排名策略
     *
     * @return  排名后的数据
     */
    default List<T> doRank(List<T> nonNullSortedList,  RankStrategy rankStrategy) {
        // 非空校验、不含null校验
        if (nonNullSortedList == null || nonNullSortedList.size() == 0) {
            throw new IllegalArgumentException("nonNullSortedList cannot be empty.");
        }
        if (nonNullSortedList.contains(null)) {
            throw new IllegalArgumentException("nonNullSortedList cannot contain null.");
        }
        // 筛选出哪些需要排名、哪些不需要排名
        List<T> notNeedRankList = new ArrayList<>(16);
        List<T> needRankList = new ArrayList<>(16);
        nonNullSortedList.forEach(x -> {
            if (x.shouldJoinRank()) {
                needRankList.add(x);
            } else {
                notNeedRankList.add(x);
            }
        });
        if (needRankList.size() == 0) {
            return nonNullSortedList;
        }
        // 进行排名
        List<T> sortedAndRankedList;
        switch (rankStrategy) {
            case NATURAL:
                sortedAndRankedList = natural(needRankList);
                break;
            case INDEX_POSTPONED_IF_SAME:
                sortedAndRankedList = indexPostponedIfSame(needRankList);
                break;
            case RANK_POSTPONED_IF_SAME:
                sortedAndRankedList = rankPostponedIfSame(needRankList);
                break;
            case CUSTOMIZED:
                sortedAndRankedList = customized(needRankList);
                break;
            default:
                throw new RuntimeException("un-support enums for [" + rankStrategy + "]");
        }
        // 将不需要排名的对象放置在最后
        sortedAndRankedList.addAll(notNeedRankList);
        return sortedAndRankedList;
    }
}
